package com.lloydfinch.composetour.ui.page

import android.util.Log
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Icon
import androidx.compose.material.LocalContentColor
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.AlignmentLine
import androidx.compose.ui.layout.FirstBaseline
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.layout
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.lloydfinch.composetour.bean.TodoItem
import com.lloydfinch.composetour.ui.theme.LayoutsCodeLabTheme
import kotlin.math.max
import kotlin.random.Random

/**
 * Name: CustomLayout
 * Author: lloydfinch
 * Function: CustomLayout
 * Date: 2021/11/15 6:03 下午
 * Modify: lloydfinch 2021/11/15 6:03 下午
 */


@Preview
@Composable
fun TextTest() {
    LayoutsCodeLabTheme {
        Text(text = "Hi there!", Modifier.firstBaseLineToTop(32.dp))
    }
}


/**
 * 将TextView中的文字下移一定高度
 * @receiver Modifier
 * @param firstBaseLineToTop Dp
 * @return Modifier
 */
fun Modifier.firstBaseLineToTop(firstBaseLineToTop: Dp) = this.then(
    layout { measurable, constraints ->
        val placeable = measurable.measure(constraints)
        check(placeable[FirstBaseline] != AlignmentLine.Unspecified)
        val firstBaseLine = placeable[FirstBaseline]
        val placeableY = firstBaseLineToTop.roundToPx() - firstBaseLine
        val height = placeable.height + placeableY
        layout(placeable.width, height) {
            placeable.placeRelative(0, placeableY)
        }
    }
)

/**
 * 简易Column
 * @param modifier Modifier
 * @param content [@androidx.compose.runtime.Composable]
 */
@Composable
fun MyColumn(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
    Layout(modifier = modifier, content = content) { measurables, constraints ->
        val placeables = measurables.map { measurable ->
            measurable.measure(constraints)
        }

        var yPosition = 0
        layout(constraints.maxWidth, constraints.maxHeight) {
            placeables.forEach { placeable ->
                placeable.placeRelative(0, yPosition)
                yPosition += placeable.height
            }
        }
    }
}


/**
 * 简易瀑布流布局
 */
@Composable
fun MyStruggledGrid(modifier: Modifier = Modifier, rows: Int = 3, content: @Composable () -> Unit) {
    Layout(modifier = modifier, content = content) { measurables, constraints ->

        // 保存每行的宽度
        val rowWidths = IntArray(rows) { 0 }
        // 保存每行的最大高度
        val rowHeights = IntArray(rows) { 0 }

        // 遍历测量
        val placeables = measurables.mapIndexed { index, measurable ->
            val placeable = measurable.measure(constraints)
            val row = index % rows
            rowWidths[row] += placeable.width
            rowHeights[row] = max(rowHeights[row], placeable.height)
            placeable
        }

        // 布局的宽度，取最宽的那个
        val width = rowWidths.maxOrNull()?.coerceIn(constraints.minWidth, constraints.maxWidth) ?: constraints.minWidth
        // 布局的高度，取综合
        val height = rowHeights.sum().coerceIn(constraints.minHeight, constraints.maxHeight)

        // 放置每行的y坐标
        val rowY = IntArray(rows) { 0 }
        // 第一行的y坐标是0
        for (i in 1 until rows) rowY[i] = rowY[i - 1] + rowHeights[i - 1]

        // 放置每行的x坐标
        val rowX = IntArray(rows) { 0 }

        // 布局
        layout(width, height) {
            // 放置
            placeables.forEachIndexed { index, placeable ->
                val row = index % rows
                placeable.placeRelative(rowX[row], rowY[row])
                rowX[row] += placeable.width
            }
        }
    }
}

@Composable
fun TestModifier() {
    Modifier.padding(all = 10.dp)
}


@Composable
fun TodoScreen(items: List<TodoItem>, onAddItem: (TodoItem) -> Unit, onRemoveItem: (TodoItem) -> Unit) {
    Log.d("TodoScreen", "data:${items.size}")
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .background(color = Color.Blue, shape = RoundedCornerShape(size = 16.dp))
            .padding(16.dp)
    ) {
        LazyColumn {
            items(items = items) { item ->
                TodoItem(item = item, onItemClick = onAddItem, onButtonClick = onRemoveItem)
            }
        }
    }
}

@Composable
fun TodoItem(item: TodoItem, onItemClick: (TodoItem) -> Unit, onButtonClick: (TodoItem) -> Unit) {
    Row(modifier = Modifier
        .fillMaxWidth()
        .clickable { onItemClick(item) },
        horizontalArrangement = Arrangement.SpaceBetween
    ) {
        Text(text = item.text)
        //val iconAlpha = randomTint() // 这一行会产生附带效应
        val iconAlpha: Float = remember { randomTint() } // 使用remember记录到内存中，
        //val iconAlpha2: Float = remember("key") { randomTint() }
        Icon(imageVector = item.icon, tint = LocalContentColor.current.copy(alpha = iconAlpha), contentDescription = null)
        Image(imageVector = item.icon, contentDescription = null, modifier = Modifier.clickable { onButtonClick(item) })
    }
}

/**
 * 获取随机浮点数，范围[0.3 - 0.9]
 * @return Float
 */
private fun randomTint(): Float {
    return Random.nextFloat().coerceIn(0.3f, 0.9f)
}

@Preview
@Composable
fun Preview() {
    val articles = listOf(
        "android",
        "kotlin",
        "java",
        "flutter",
        "vue",
        "spring",
        "android",
        "kotlin",
        "java",
        "flutter",
        "vue",
        "spring",
        "android",
        "kotlin",
        "java",
        "flutter",
        "vue",
        "spring"
    )

    MyStruggledGrid(rows = 5) {
        articles.forEach { article ->
            Text(text = article, modifier = Modifier.padding(8.dp))
        }
    }
}